package com.enbatis.mybatisplugs.commons.utils;

import com.enbatis.mybatisplugs.commons.annotation.Exclude;
import com.enbatis.mybatisplugs.commons.annotation.PrimaryKey;
import com.enbatis.mybatisplugs.commons.sql.Wrapper;
import com.enbatis.mybatisplugs.enums.CreateSqlEnum;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.jdbc.SQL;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class BaseSqlProvider<T>  {


    @Options
    public String insert(T entity) {

        SQL sql = new SQL();

        Class clazz = entity.getClass();

        String tableName = clazz.getSimpleName();

        String realTableName = LineHumpUtil.humpToLine(tableName);
        sql.INSERT_INTO(realTableName);

        List<Field> fields = getFields(clazz);
        for (Field field : fields) {

            field.setAccessible(true);

            String column = field.getName();
            sql.VALUES(LineHumpUtil.humpToLine(column), String.format("#{" + column + "}"));

        }

        return sql.toString();
    }



    @Options
    public String saveBatch(Collection<T> list, Class clazz) {

        StringBuilder sb = new StringBuilder();
        String tableName = clazz.getSimpleName();

        String realTableName = LineHumpUtil.humpToLine(tableName);
        sb.append("INSERT INTO  "+realTableName+" ( ");

        List<Field> fields = getFields(clazz);

       StringBuilder patten=new StringBuilder("(");

        for (Field field : fields) {
            field.setAccessible(true);
            String column = field.getName();
            sb.append(LineHumpUtil.humpToLine(column)+" ,");


            patten.append("#'{'list[{0}].").append(column).append("},");

        }
        sb.deleteCharAt(sb.length()-1);
        sb.append(" ) ");

        sb.append("VALUES ");


        patten.deleteCharAt(patten.length()-1);

        patten.append(")");
        MessageFormat mf=new MessageFormat(patten.toString());

        for (int i = 0; i < list.size(); i++) {
            sb.append(mf.format(new Object[]{i}));
            if (i < list.size() - 1) {
                sb.append(",");
            }
        }


        return sb.toString();
    }






    public String deleteById(String tableName,Serializable id) {
        CreateSqlEnum createSqlEnum=CreateSqlEnum.DELETE_BY_ID;
        if (null==id||StringUtils.isBlank(tableName)){
            return "";
        }
        return  String.format(createSqlEnum.getSql(),tableName,"id","id");
    }





    private List<Field> getPrimarkKeyFields(Class clazz) {

        List<Field> primaryKeyField = new ArrayList<>();
        List<Field> fields = getFields(clazz);
        for (Field field : fields) {
            field.setAccessible(true);
            PrimaryKey key = field.getAnnotation(PrimaryKey.class);
            if (key != null) {
                primaryKeyField.add(field);
            }

        }
        return primaryKeyField;
    }

    private List<Field> getFields(Class clazz) {

        List<Field> fieldList = new ArrayList<>();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            Exclude key = field.getAnnotation(Exclude.class);
            if (key == null) {
                fieldList.add(field);
            }

        }
        return fieldList;
    }

    public String getById(String tableName, Serializable id) {
        if (null==id||StringUtils.isBlank(tableName)){
            return "";
        }
        SQL sql = new SQL();
        sql.SELECT("*").FROM(tableName);
        sql.WHERE("id" + "=" + String.format("#{id}"));
        System.out.println("getSql:"+sql.toString());
        return sql.toString();
    }



    public String list(Wrapper<T> wrapper){


        StringBuilder sb = new StringBuilder("SELECT ");

        Class clazz = wrapper.getEntity().getClass();
        String tableName = clazz.getSimpleName();
        String realTableName = LineHumpUtil.humpToLine(tableName);
        String column=wrapper.getSqlSelect();

        if (StringUtils.isNotBlank(column)){
            sb.append(column+" FROM "+ realTableName+" WHERE 1=1 ");
        }else{
            sb.append(" * FROM "+ realTableName +" WHERE 1=1 ");
        }
        sb.append(wrapper.getWholeQuerySql());
        return  sb.toString();
    }



    public String selectCount(Wrapper<T> wrapper){
        StringBuilder sb = new StringBuilder("SELECT COUNT(1) FROM  ");
        Class clazz = wrapper.getEntity().getClass();
        String tableName = clazz.getSimpleName();
        String realTableName = LineHumpUtil.humpToLine(tableName);
        sb.append(realTableName).append(" WHERE 1=1 ");

        sb.append(wrapper.getWholeQuerySql());
        return  sb.toString();
    }



    public String update(T bean,Wrapper<T> wrapper) {
        SQL sql = new SQL();
        Class clazz = bean.getClass();
        String tableName = clazz.getSimpleName();
        String realTableName = LineHumpUtil.humpToLine(tableName);
        sql.UPDATE(realTableName);
        List<Field> fields = getFields(clazz);
        for (Field field : fields) {

            field.setAccessible(true);

            String column = field.getName();

            if (column.equals("id")) {
                continue;
            }
            sql.SET(LineHumpUtil.humpToLine(column) + "=" + String.format("#{bean." + column + "}"));
        }

        StringBuilder sb=new StringBuilder(" 1=1 ");

        sb.append(wrapper.getWholeQuerySql());

        sql.WHERE(sb.toString());
        System.out.println("updateSql:"+sql.toString());
        return sql.toString();

    }

    public String updateById(String tableName,T bean) {

        SQL sql = new SQL();

        String realTableName = LineHumpUtil.humpToLine(tableName);
        sql.UPDATE(realTableName);

        List<Field> fields = getFields(bean.getClass());
        for (Field field : fields) {

            field.setAccessible(true);

            String column = field.getName();

            if (column.equals("id")) {
                continue;
            }

            System.out.println(LineHumpUtil.humpToLine(column));


            sql.SET(LineHumpUtil.humpToLine(column) + "=" + String.format("#{bean." + column + "}"));
        }





        boolean it=true;
        for (Field pkField : fields) {
                pkField.setAccessible(true);
                String column = pkField.getName();

                if (column.equals("id")) {
                    it=false;
                    sql.WHERE("id" + "=" + String.format("#{bean.id}"));
                    break;
                }


            }
          if (it){
              sql.WHERE("1=2");
          }
        System.out.println("updateSql:"+sql.toString());
        return sql.toString();

    }

}
